package partThree;

import java.util.Objects;

/* 本类用于顶级父类Object的入门案例*/
public class TestObject {
    public static void main(String[] args) {
        //4.创建学生类的对象，进行测试
        Student s = new Student();
        Student s1 = new Student("海绵宝宝",3);
        Student s2 = new Student("海绵宝宝",3);

        //5. 测试hashCode()
        /* 本方法的作用是返回对应对象的int类型的哈希码值
         * 本方法力求不同的对象返回的哈希码不同
         * 这样我们就可以根据哈希码值区分不同的对象*/
        System.out.println(s.hashCode());
        System.out.println(s1.hashCode());
        System.out.println(s2.hashCode());

        //6. 测试toString()
        /* 打印s对象的是println（），这个方法会层层调用，一直到Object中的toString（）
         * Object中toString（）的默认实现：对象的名字@十六进制的哈希码值
         * 但是子类重写了toString方法以后，打印的是对象的类型+属性+属性值*/
        System.out.println(s);
        System.out.println(s1);

        //8.测试equals方法
        /* Object中equals()的默认实现使用的是==比较
         * ==比较的是左右俩边的值，如果是基本类型，比较的是字面值，不如1和1,3.4和4.3
         * 如果是引用类型，比较的是引用类型保持的地址值*/
        System.out.println(s1.equals(s2));
    }
}
//1.创建一个学生类
class Student{
    //2.定义属性
    String name;  //姓名
    int age; //年龄
    //3.1 添加本类的无参构造
    public Student() {
        System.out.println("我是无参构造");
    }
    //3.2 添加本类的全参构造
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("我是全参构造");
    }

    //7. 在student类中，添加重写的toString方法
//右键--Generate--toString
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    //9. 添加重写的equals与hashCode
    /* equals方法与hashCode方法，逻辑保持一致，要重写都重写，要不重写都不重写
     * 如果不重写：hashCode()的哈希码根据地址值生成
     *           equals()底层使用==比较俩个对象的地址值
     * 如果重写了：hashCode()的哈希码根据重写传入的属性值生成
     *          equals()比较的是重写后的类型+所有属性与属性值
     * 重写方法：右键-----Generate--equals() and hashCode()*/
    @Override
    public boolean equals(Object o) {
        // 前提：this代表的是调用本方法对象s1  o代表的是传入的对象s2
        // 1.比较俩个对象的地址值，如果==为true，证明直接就是同一个对象
        // 后续就不用比较了，直接返回true
        if (this == o) return true;
        // 2.1如果传入的对象是null，说明实际上并没有对象，还是引用类型的默认值
        // 2.2如果俩个对象获取类型不一致，比如一个是Cat类型，一个是Car类型
        // 以上俩种情况，只要满足一种，不符合条件，返回false
        if (o == null || getClass() != o.getClass()) return false;
        // 3.传入对象的类型是Object，父类无法使用子类的特有属性，所以需要强转
        /* 多态：向上造型，把子类看做是父类型， Animal a = new Cat();
           向下造型:之前转成父类型的子类对象，又想使用子类自己的特有功能了，可以向下转型
           写法：Cat c = (Cat) a ;*/
        // 向下造型：把父类型Object转回子类型student
        Student student = (Student) o;
        //4.比较的是俩个对象的属性与属性值
        // 如果是基本类型，直接比较值，所以用==
        // 如果是引用类型，比较的是地址值，所以用Objects.equals
        return age == student.age && Objects.equals(name, student.name);
    }
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}